const fs = window.require('fs');
export default class Model {
  constructor(option) {
    this.Vm = option.Vm;
    this.viewer = option.viewer;
    this.modelList = [];
  }

  // 加载模型
  loadModel (option) {
    const { serverType, callback } = option;
    switch (serverType) {
      case 'glb':
      case 'gltf':
        this.loadFromGltf(option);
        break;

      case '3DTileset':
        this.load3DTileset(option);
        break;

      default:
        break;
    }

    typeof callback == 'function' && callback();
  }

  // glb、gltf
  loadFromGltf (option) {
    const { resourceId, serverUrl, position, scale, isFirst } = option;
    const show = option.hasOwnProperty('show') ? option.show : false;
    if (!position) return;
    let curModel = this.modelList.find(el => el.attribute.resourceId == resourceId);
    if (curModel) return;
    let lng, lat, height, heading, pitch, roll;
    lng = position.lng || '';
    lat = position.lat || '';
    height = position.height || '';
    heading = position.heading || 0;
    pitch = position.pitch || 0;
    roll = position.roll || 0;
    if (!lng || !lat || !height) return;
    const cartesian3 = Cesium.Cartesian3.fromDegrees(lng, lat, height);
    const hpRoll = new Cesium.HeadingPitchRoll(Cesium.Math.toRadians(heading), Cesium.Math.toRadians(pitch), Cesium.Math.toRadians(roll));
    const c = Cesium.Transforms.eastNorthUpToFixedFrame;
    let m = Cesium.Transforms.headingPitchRollToFixedFrame(cartesian3, hpRoll, Cesium.Ellipsoid.WGS84, c);
    if (scale) Cesium.Matrix4.multiplyByUniformScale(m, scale, m);
    this.viewer.scene.logarithmicDepthBuffer = true;

    curModel = this.viewer.scene.primitives.add(Cesium.Model.fromGltf({
      url: serverUrl,
      modelMatrix: m,
    }));
    option.position = { lng, lat, height, heading, pitch, roll };
    curModel.show = show;
    curModel.attribute = option;
    this.modelList.push(curModel);

    if (isFirst) this.setView({ lng, lat, height, heading, pitch, roll });
  }

  // 三维服务
  load3DTileset (option) {
    const { resourceId, serverUrl, isFirst } = option;
    const show = option.hasOwnProperty('show') ? option.show : false;
    let curModel = this.modelList.find(el => el.attribute.resourceId == resourceId);
    if (curModel) return;
    console.log('执行js文件加载三维');
    curModel = new Cesium.Cesium3DTileset({
      url: serverUrl,
      skipLevelOfDetail: true,
      maximumScreenSpaceError: window.modelConfig.maximumScreenSpaceError, // 数值加大，能让最终成像变模糊
      skipScreenSpaceErrorFactor: window.modelConfig.skipScreenSpaceErrorFactor,
      skipLevels: window.modelConfig.skipLevels,
      immediatelyLoadDesiredLevelOfDetail: false,
      loadSiblings: true, // 如果为true则不会在已加载完概况模型后，自动从中心开始超清化模型
      cullWithChildrenBounds: true,
      cullRequestsWhileMoving: true,
      cullRequestsWhileMovingMultiplier: 10, // 值越小能够更快的剔除
      preloadWhenHidden: true,
      preferLeaves: true,
      maximumMemoryUsage: window.modelConfig.maximumMemoryUsage, // 内存分配变小有利于倾斜摄影数据回收，提升性能体验
      progressiveResolutionHeightFraction: 0.5, // 数值偏于0能够让初始加载变得模糊
      dynamicScreenSpaceErrorDensity: 0.5, // 数值加大，能让周边加载变快
      dynamicScreenSpaceError: true, // 根据测试，有了这个后，会在真正的全屏加载完之后才清晰化模型
      useIndexDB: false
    });
    curModel.show = show;
    curModel.attribute = option;
    this.viewer.scene.primitives.add(curModel);
    this.modelList.push(curModel);

    if (isFirst) {
      curModel.readyPromise.then((tileset) => {
        this.viewer.zoomTo(tileset);
      });
    }
  }

  // 模型显隐
  hideModel (resourceId, state) {
    let curModel = this.modelList.find(el => el.attribute.resourceId == resourceId);
    if (curModel) {
      curModel.show = state;
      curModel.attribute.show = state;
    }
  }

  // 模型定位
  locateModel (resourceId) {
    let curModel = this.modelList.find(el => el.attribute.resourceId == resourceId);
    if (curModel && curModel.attribute.isExist) {
      if (curModel.attribute.position) {
        const { lng, lat, height } = curModel.attribute.position;
        this.setView({ lng, lat, height });
      } else {
        this.viewer.camera.flyToBoundingSphere(curModel.boundingSphere, {
          duration: 2,
          easingFunction: Cesium.EasingFunction.LINEAR_NONE,
          offset: {
            heading: Cesium.Math.toRadians(0),
            pitch: Cesium.Math.toRadians(-35.0),
            roll: 0.0,
          }
        });
      }
    }
  }

  // 删除模型
  removeModel (resourceId = '') {
    if (this.modelList.length) {
      if (resourceId) {
        for (let i = 0; i < this.modelList.length; i++) {
          const item = this.modelList[i];
          if (item.attribute.resourceId == resourceId) {
            this.viewer.scene.primitives.remove(item);
            this.modelList.splice(i, 1);
            i++;
          }
        }
      } else {
        for (let i = 0; i < this.modelList.length; i++) {
          const item = this.modelList[i];
          this.viewer.scene.primitives.remove(item);
        }
        this.modelList = [];
      }
    }
  }

  setView (position, callback) {
    const { lng, lat, height, heading, pitch, roll } = position;
    if (!lng || !lat || !height) return;
    this.viewer.camera.setView({
      destination: Cesium.Cartesian3.fromDegrees(lng, lat, height + 200),
      orientation: { heading: Cesium.Math.toRadians(heading || 0), pitch: Cesium.Math.toRadians(pitch || -90), roll: Cesium.Math.toRadians(roll || 0) },
      complete: callback && callback()
    });
  };

  loadModelFile (data) {
    for (let i = 0; i < data.length; i++) {
      const item = data[i];
      const attribute = item.attribute || null;
      const isExist = attribute.isExist || '';
      if (!attribute || !isExist) break;
      this.loadModel(attribute);
    }
  }

  destroy () {
    this.removeModel();
  }
}